Technical Q&A QA1243
How can I verify that a Movie can actually draw into a non-RGB GWorld?


Q: ムービーが実際に 非 RGB GWorld へ描画できることを確認できますか?たとえば、'2vuy' (k2vuyPixelFormat) ピクセル形式の GWorld を作成した場合、一部のムービーだけはこの形式で描画されますが、それ以外は単に空のフレームが描画されるようです。

A: 2 つの方法で、非 RGB GWorld にムービーを描画できるかどうかを確認できます。

すべてのイメージデコンプレッサが非 RGB 出力をサポートするわけではありません。複数のビデオトラック、エフェクト、複数のコーデック型、変換マトリックスなどを持つ複雑なムービーは、QuickTime が非 RGB の色空間では表現できないさまざまな合成を必要とします。

1 つ目の方法は、合成または複雑なマトリックスを含まず、1 つのイメージ記述をもつビデオトラックがムービーに 1 つしかなく、そのビデオ形式が出力先として非 RGB ピクセル形式をサポートするかどうかを確かめて、ムービーの単純性を調べます。リスト 1 を参照してください。

注記:
この方法は、非 RGB ピクセル形式に描画できる一部のムービーを受け付けないことがあります。


リスト 1. 指定されたピクセル形式にムービーを描画できるかどうか

Boolean CanRenderMovieToPixelFormat(Movie  inMovie,
                                    OSType inPixelFormat)
{
  Track videoTrack, secondVisualTrack;
  ImageDescriptionHandle imageDesc = NULL;
  Boolean canRenderNonRGB = false;
  MatrixRecord matrix;
  Media videoMedia;
  OSType codecType;
  ComponentDescription cd = { decompressorComponentType, 0, 0, 0,
                              cmpIsMissing };
  Component decompressor = 0;

  // 値 1、2、4、8、16、24、32 は標準 RGB ピクセル形式を指定し、
  // 値 33、34、36、40 は標準グレースケールのピクセル形式を指定する。
  // これらのピクセル形式には、このアプローチは使用しないこと
  if (inPixelFormat <= 40) return true;

  // ムービーのマトリックスが「scale」+「translate」と同じかどうかチェック
  GetMovieMatrix(inMovie, &matrix);
  if (GetMatrixType(&matrix) > scaleTranslateMatrixType) goto nope;

  // 1 つ目のビデオトラックを取得
  videoTrack = GetMovieIndTrackType(inMovie, 1, VideoMediaType,
                                    movieTrackMediaType);
  if (!videoTrack) goto nope;

  // ほかのビジュアルトラックがないことを確認
  // (ビデオトラックは常にビジュアル)
  secondVisualTrack = GetMovieIndTrackType(inMovie, 2,
                                        VisualMediaCharacteristic,
                                        movieTrackCharacteristic);
  if (secondVisualTrack) goto nope;

  // ビデオトラックのマトリックスが「scale」+「translate」と同じかどうかチェック
  GetTrackMatrix(videoTrack, &matrix);
  if (GetMatrixType(&matrix) > scaleTranslateMatrixType) goto nope;

  // サンプル記述が 1 つしかないことを確認
  videoMedia = GetTrackMedia(videoTrack);
  if (1 != GetMediaSampleDescriptionCount(videoMedia)) goto nope;

  // そのサンプル記述からコーデック型を取得
  imageDesc = (ImageDescriptionHandle)NewHandle(0);
  GetMediaSampleDescription(videoMedia, 1,
                            (SampleDescriptionHandle)imageDesc);
  if (noErr != GetMoviesError()) goto nope;
  codecType = (*imageDesc)->cType;

  // このコーデック型のデコンプレッサを見つける。cpix パブリックリソースに、
  // 一致するピクセル形式がリストされているものを、少なくとも 1 つ見つける
  cd.componentSubType = codecType;
  decompressor = FindNextComponent(0, &cd);
  if (!decompressor) goto nope;

  do {
    Handle cpix = NULL;
    // 'cpix' リソースは、サポートされている非 RGB ピクセル形式をリストする
    // ために、コーデックによって使用される
    if (noErr == GetComponentPublicResource(decompressor,
                         FOUR_CHAR_CODE('cpix'), 1, &cpix)) {
      int i;
      int cpixFormatCount = GetHandleSize(cpix) / sizeof(OSType);
      for (i = 0; i < cpixFormatCount; i++) {
        if (inPixelformat == (*(OSType**)cpix)[i]) {
          canRenderNonRGB = true;
        }
      }
      DisposeHandle( cpix );
    }
    decompressor = FindNextComponent(decompressor, &cd);
  } while (decompressor && false == canRenderNonRGB);

nope:
  if (imageDesc) DisposeHandle((Handle)imageDesc);

  return canRenderNonRGB;
}

もう 1 つの方法では、指定されたピクセル形式への描画を試み、それが成功したかどうかを調べます。リスト 2 を参照してください。

警告:
クラッシュして失敗する恐れがあるので、この方法を QuickTime 6 以前のバージョンで使用するべきではありません。


リスト 2. 指定されたピクセル形式へのムービーの描画実行
OSErr TryToRenderMovieToPixelFormat(Movie inMovie, 
                                    OSType inPixelFormat)
{
  OSErr err;
  Rect bounds;
  CGrafPtr savePort;
  GDHandle saveDevice;
  GWorldPtr gworld = NULL;

  GetMovieGWorld(inMovie, &savePort, &saveDevice);

  GetMovieBox(inMovie, &bounds);
  err = QTNewGWorld(&gworld, inPixelFormat, &bounds, NULL, NULL, 0);
  if (err) goto bail;
  LockPixels(GetGWorldPixMap(gworld));

  SetMovieGWorld(inMovie, gworld, NULL);
  MoviesTask(inMovie, 0);
  err = GetMovieStatus(inMovie, NULL);

bail:
  SetMovieGWorld(inMovie, savePort, saveDevice);
  if (gworld) DisposeGWorld(gworld);

  return err;
}

ムービーを特定の非 RGB GWorld に描画できることを確認するときには、上記のテクニックを両方とも使うことをお勧めします。まず、ムービーが目的のピクセル形式への描画をサポートするかどうかを確認し、次に、実際に描画してみます。どちらかの手順が失敗した場合は、32ARGB (k32ARGBPixelFormat) GWorld に戻ります。


[2003 年 3 月 5 日]